<!DOCTYPE html>
<html lang="en">
    <head>
            <meta charset="utf-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta content="Bmob,BmobCloud,bomb,BaaS,mBaaS,PaaS,Serverless,FaaS,Function as a Service,Backend as a Service,serverless computing,cloud function,后端云,bmob后端云,小程序云,小程序后端,云数据库,云存储,文件存储,云函数,云端代码,定时任务,游戏后端,游戏云,用户系统,无服务器函数,移动开发,app开发,小程序开发,云端一体化,互联网中间件" name="keywords"/>
            <meta content="国内首家专注于移动应用Serverless云服务的平台,Bmob后端云让移动开发更简单,全方位一体化的后端服务平台" name="description"/>
            
            
            
            <link rel="shortcut icon" href="../../img/favicon.ico">
        
        <script type="text/javascript" src="//game.bmob.cn/static/doc_union.js"></script>
            <!--
            <title>Kotlin - Bmob文档中心</title>
            -->
            <title>数据存储 &middot; Kotlin – Bmob后端云 </title>        
            
            <link href="../../css/bootstrap-custom.min.css" rel="stylesheet">
            <link href="../../css/font-awesome-4.5.0.css" rel="stylesheet">
            <link href="../../css/base.css" rel="stylesheet">
            <link rel="stylesheet" href="../../css/highlight.css">
            <link href="../../css/agate.css" rel="stylesheet">
            <link href="../../css/custom.css" rel="stylesheet" id="custom">
    </head>

    <body >

        <div class="navbar navbar-fixed-top" role="navigation">
    <div class="main-nav">
        <!-- Collapsed navigation -->
        <div class="navbar-header">
            <a class="navbar-brand" href="../..">
                <!--Bmob文档中心-->
                <img src="../../img/logo.png" alt="">
            </a>
        </div>

        <!-- Expanded navigation -->
        <div class="navbar-collapse collapse">

          <ul class="nav navbar-nav">
            
              <li class="pull-left">
                
					<a href="../..">文档首页</a>
                
              </li>
            
              <li class="pull-left active">
                
					<!--<a href="">数据服务</a>-->
					<li class="dropdown active">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">数据服务 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            
								<li >
									<a href="../android/">Android</a>
                                </li>
                            
                            
								<li >
									<a href="../ios/">iOS</a>
                                </li>
                            
                            
								<li >
									<a href="../csharp/">C#</a>
                                </li>
                            
                            
								<li >
									<a href="../php/">PHP</a>
                                </li>
                            
                            
								<li >
									<a href="../go/">GO</a>
                                </li>
                            
                            
								<li >
									<a href="../restful/">REST API</a>
                                </li>
                            
                            
								<li >
									<a href="../wechat_app_new/rm/">JavaScript</a>
                                </li>
                            
                            
                                <li >
                                    <a href="../cocos2d_x/">Cocos2D-X</a>
                                </li>
							
                            
								<li >
									<a href="../wechat_app/">小程序</a>
                                </li>
                            
                            
                                <li >
                                    <a href="../wechat_app_new/">快应用</a>
                                </li>
							
                            
                                <li >
                                    <a href="../wechat_app_new/">Nodejs</a>
                                </li>
							
                            
                                <li >
                                    <a href="../wechat_app_new/">Cocos Creator</a>
                                </li>
							
                            
								<li >
									<a href="../wechat_app_new/rm/">小程序(新)</a>
                                </li>
                            
                            
                                <li class="active">
                                    <a href="./">Kotlin</a>
                                </li>
							
                            
                                <li >
                                    <a href="../python/">Python</a>
                                </li>
							
                        </ul>
                    </li>
                
              </li>
            
              <li class="pull-left">
                
					<!--<a href="../../cloud_function/android/">云函数</a>-->
					<li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">云函数 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            
                                <li >
                                    <a href="../../cloud_function/android/">Android</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../cloud_function/ios/">iOS</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../cloud_function/java/">Java</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../cloud_function/python/">Python</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../cloud_function/csharp/">C#</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../cloud_function/php/">PHP</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../cloud_function/javascript/">JavaScript</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../cloud_function/restful/">REST API</a>
                                </li>
							
                            
								<li >
									<a href="../../cloud_function/web/">Web</a>
                                </li>
                            
                        </ul>
                    </li>
                
              </li>
            
              <li class="pull-left">
                
					<!--<a href="../../sms/android/">短信服务</a>-->
					<li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">短信服务 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            
                                <li >
                                    <a href="../../sms/android/">Android</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../sms/ios/">iOS</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../sms/php/">PHP</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../sms/javascript/">JavaScript</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../sms/restful/">REST API</a>
                                </li>
							
                        </ul>
                    </li>
                
              </li>
            
              <li class="pull-left">
                
					<!--<a href="">游戏实时后端</a>-->
					<li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">游戏实时后端 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            
								<li >
									<a href="../../game/unity/quick_start/">Unity</a>
                                </li>
                            
                            
								<li >
									<a href="../../game/cocos_creator/quick_start/">Cocos Creator</a>
                                </li>
                            
                            
								<li >
									<a href="../../game/wechat_games/quick_start/">微信小游戏</a>
                                </li>
                            
                            
                                <li >
                                    <a href="../../game/cloud_function/develop_doc/">云函数</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../game/classic_case/">经典案例</a>
                                </li>
							
                        </ul>
                    </li>
                
              </li>
            
              <li class="pull-left">
                
					<!--<a href="">即时通讯</a>-->
					<li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">即时通讯 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            
								<li >
									<a href="../../im/android/">Android</a>
                                </li>
                            
                            
								<li >
									<a href="../../im/ios/">iOS</a>
                                </li>
                            
                        </ul>
                    </li>
                
              </li>
            
              <li class="pull-left">
                
					<!--<a href="../../push/android/">推送服务</a>-->
					<li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">推送服务 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            
                                <li >
                                    <a href="../../push/android/">Android</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../push/ios/">iOS</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../push/php/">PHP</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../push/javascript/">JavaScript</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../push/restful/">REST API</a>
                                </li>
							
                        </ul>
                    </li>
                
              </li>
            
              <li class="pull-left">
                
					<!--<a href="../../other/common_problem/">其他</a>-->
					<li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">其他 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            
                                <li >
                                    <a href="../../other/common_problem/">常见问题</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../other/error_code/">错误码</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../other/data_safety/">数据安全</a>
                                </li>
							
                            
                                <li >
                                    <a href="../../other/bql/">BQL</a>
                                </li>
							
                        </ul>
                    </li>
                
              </li>
            
              <li>
                  <a href="https://www.bmob.cn/repository/index" target="_blank">知识库</a>
              </li>
              <li>
                  <a href="http://doc.bmob.cn/video/index.html" target="_blank">视频教程</a>
              </li>
            </ul>
            
        </div>
    </div>
</div>

        <div class="pagebody" id="main-wrapper">
            <div class="sidebar">
                <div class="bs-sidebar hidden-print affix well" role="complementary">

	
		
	
		
				
				
				
				
				
				
				
				
				
				
				
				
				
				
					<div class="code-title">Kotlin</div>
				
				
		
	
		
				
				
				
				
				
				
				
				
				
		
	
		
				
				
				
				
				
		
	
		
				
				
				
				
				
		
	
		
				
				
		
	
		
				
				
				
				
				
		
	
		
				
				
				
				
		
	


	<ul class="nav bs-sidenav">
		
			
		
			
				
					
						
					
						
					
						
					
						
					
						
					
						
					
						
					
						
					
						
					
						
					
						
					
						
					
						
					
						
							
								
									
										<li class="active "><a href="#bmob-android-data-sdk-kotlin-demo">bmob-android-data-sdk-kotlin-demo</a>
											
										</li>
									
										<li class=""><a href="#_1">集成</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_2">开发工具</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_3">仓库配置</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_4">依赖配置</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_5">权限注册</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_6">初始化</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_7">数据类型</a>
											
										</li>
									
										<li class=""><a href="#_8">默认表</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_9">添加一行数据</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_10">更新一条数据</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_11">删除一条数据</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_12">查询一条数据</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_13">查询多条数据</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_14">批量数据操作</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_15">批量新增数据</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_16">批量更新数据</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_17">批量删除操作</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_18">批量新增、更新、删除同步操作</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_19">注册登录</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_20">用户名密码注册</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_21">用户名密码登录</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_22">修改密码</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_23">文件管理</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_24">权限</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_25">上传单个文件</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_26">关联线上文件和表字段</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_27">上传多个文件</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_28">删除单个文件</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_29">删除多个文件</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_30">短信</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_31">发送短信验证码</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_32">验证短信验证码</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_33">邮箱</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_34">验证激活</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_35">重置密码</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_36">邮箱+密码登录</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_37">第三方账号</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_38">注册登录</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_39">账号关联</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_40">取消关联</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_41">版本更新</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_42">版本更新设置</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_43">动态访问权限</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_44">清单文件设置</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_45">数据监听</a>
											
										</li>
									
										<li class=""><a href="#acl">ACL</a>
											
										</li>
									
										<li class=""><a href="#_46">角色</a>
											
										</li>
									
										<li class=""><a href="#_47">数组</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_48">添加数组</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_49">更新数组</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_50">删除数组</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_51">位置</a>
											
										</li>
									
										<li class=""><a href="#_52">关联关系</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_53">一对一关联</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_56">一对多关联</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_59">多对多关联</a></li>
											</ul>
											
										</li>
									
										<li class=""><a href="#_63">服务器时间</a>
											
										</li>
									
										<li class=""><a href="#_64">表结构</a>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_65">获取单表结构</a></li>
											</ul>
											
											<ul class="nav nav-l2">
												<li><a class="itm-l2" href="#_66">获取所有表结构</a></li>
											</ul>
											
										</li>
									
								
							
						
					
						
					
				
			
		
			
		
			
		
			
		
			
		
			
		
			
		
	</ul>
</div>
            </div>
            <div class="content" role="main">
                <div class="wrap">
                    

<h1 id="bmob-android-data-sdk-kotlin-demo">bmob-android-data-sdk-kotlin-demo<a class="headerlink" href="#bmob-android-data-sdk-kotlin-demo" title="Permanent link">&para;</a></h1>
<p>Kotlin已正式成为Android官方支持开发语言，具体使用可参考：</p>
<pre><code>http://kotlinlang.org/docs/reference/android-overview.html
</code></pre>

<p>由于Kotlin和Java之间具有可互操作性，为方便广大Bmob的Kotlin开发者，特开发此案例，展示如何使用Kotlin来调用Bmob的Android数据服务SDK。</p>
<p>案例地址：</p>
<pre><code>https://github.com/bmob/bmob-android-data-sdk-kotlin-demo
</code></pre>

<h1 id="_1">集成<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h1>
<h2 id="_2">开发工具<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h2>
<p>Android Studio，具体使用可参考：</p>
<pre><code>http://www.android-studio.org/
</code></pre>

<h2 id="_3">仓库配置<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h2>
<p>在项目build.gradle的allprojects-repositories节点下配置：</p>
<pre><code>maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
</code></pre>
<h2 id="_4">依赖配置<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h2>
<p>在应用build.gradle的dependencies节点下配置，其中x.y.z为数据服务SDK版本号码：</p>
<pre><code>implementation 'cn.bmob.android:bmob-sdk:x.y.z'
</code></pre>
<h2 id="_5">权限注册<a class="headerlink" href="#_5" title="Permanent link">&para;</a></h2>
<p>在清单文件注册所需权限：</p>
<pre><code>&lt;!-- 允许联网 --&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;!-- 获取GSM（2g）、WCDMA（联通3g）等网络状态的信息 --&gt;
&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
&lt;!-- 获取wifi网络状态的信息 --&gt;
&lt;uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /&gt;
&lt;!-- 保持CPU 运转，屏幕和键盘灯有可能是关闭的,用于文件上传和下载 --&gt;
&lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
&lt;!-- 获取sd卡写的权限，用于文件上传和下载 --&gt;
&lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
&lt;!-- 允许读取手机状态 用于创建BmobInstallation --&gt;
&lt;uses-permission android:name="android.permission.READ_PHONE_STATE" /&gt;
&lt;!-- 请求安装APK，用于版本更新 --&gt;
&lt;uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /&gt;
</code></pre>
<h2 id="_6">初始化<a class="headerlink" href="#_6" title="Permanent link">&para;</a></h2>
<p>在应用主进程中进行代码初始化，BMOB_APP_ID请到应用设置中获取：</p>
<pre><code>Bmob.initialize(this,Constant.BMOB_APP_ID)
</code></pre>
<h1 id="_7">数据类型<a class="headerlink" href="#_7" title="Permanent link">&para;</a></h1>
<table>
<thead>
<tr>
<th>Web端类型</th>
<th>支持的Kotlin类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Number</td>
<td>Byte、Short、Int、Long、Float、Double </td>
<td>基本数据类型</td>
</tr>
<tr>
<td>Array</td>
<td>MutableList</td>
<td>数组类型</td>
</tr>
<tr>
<td>File</td>
<td>BmobFile</td>
<td>Bmob特有类型，用来标识文件类型</td>
</tr>
<tr>
<td>GeoPoint</td>
<td>BmobGeoPoint</td>
<td>Bmob特有类型，用来标识地理位置</td>
</tr>
<tr>
<td>Date</td>
<td>BmobDate</td>
<td>Bmob特有类型，用来标识日期类型</td>
</tr>
<tr>
<td>Pointer</td>
<td>特定对象</td>
<td>Bmob特有类型，用来标识指针类型</td>
</tr>
<tr>
<td>Relation</td>
<td>BmobRelation</td>
<td>Bmob特有类型，用来标识数据关联</td>
</tr>
</tbody>
</table>
<h1 id="_8">默认表<a class="headerlink" href="#_8" title="Permanent link">&para;</a></h1>
<table>
<thead>
<tr>
<th>Web端表名</th>
<th>支持的Kotlin类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>_User</td>
<td>BmobUser</td>
<td>用户系统</td>
</tr>
<tr>
<td>_Role</td>
<td>BmobRole</td>
<td>用户角色</td>
</tr>
<tr>
<td>_Installation</td>
<td>BmobInstallation</td>
<td>用户设备</td>
</tr>
<tr>
<td>_Article</td>
<td>用户自定义</td>
<td>图文消息</td>
</tr>
<tr>
<td>AppVersion</td>
<td>AppVersion</td>
<td>版本升级</td>
</tr>
<tr>
<td># 增删改查</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="_9">添加一行数据<a class="headerlink" href="#_9" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 新增一条数据
 */
private fun createOne() {
    var gameScore = GameScore()
    gameScore.playerName = "比目"
    gameScore.score = 89
    gameScore.isPay = false
    /**
     * 请不要给 gameScore.objectId 赋值，数据新增成功后将会自动给此条数据的objectId赋值并返回！
     */
    gameScore.save(object : SaveListener&lt;String&gt;() {
        override fun done(objectId: String?, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "新增数据成功：$objectId", Toast.LENGTH_LONG).show()
            } else {
                Log.e("CREATE", "新增数据失败：" + ex.message)
            }
        }
    })
}
</code></pre>
<h2 id="_10">更新一条数据<a class="headerlink" href="#_10" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * bmob更新一条数据
 */
private fun updateObject(objectId: String?) {
    var person = Person()
    person.objectId = objectId
    person.name = "更新名字+" + System.currentTimeMillis()
    person.update(object : UpdateListener() {
        override fun done(ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "删除成功", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mContext, ex.message, Toast.LENGTH_LONG).show()
            }
        }

    })
}
</code></pre>
<h2 id="_11">删除一条数据<a class="headerlink" href="#_11" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * bmob删除一条数据
 */
private fun deleteObject(objectId: String?) {
    var person = Person()
    person.objectId = objectId
    person.delete(object : UpdateListener() {
        override fun done(ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "删除成功", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mContext, ex.message, Toast.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>
<h2 id="_12">查询一条数据<a class="headerlink" href="#_12" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * bmob查询单条数据
 */
private fun getObject(objectId: String?) {
    var bmobQuery: BmobQuery&lt;Person&gt; = BmobQuery()
    bmobQuery.getObject(objectId, object : QueryListener&lt;Person&gt;() {
        override fun done(person: Person?, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "查询成功", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mContext, ex.message, Toast.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>
<h2 id="_13">查询多条数据<a class="headerlink" href="#_13" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * bmob 查询数据列表
 */
private fun queryObjects() {
    var bmobQuery: BmobQuery&lt;Person&gt; = BmobQuery()
    bmobQuery.findObjects(object : FindListener&lt;Person&gt;() {
        override fun done(persons: MutableList&lt;Person&gt;?, ex: BmobException?) {

            if (ex == null) {
                Toast.makeText(mContext, "查询成功", Toast.LENGTH_LONG).show()
                if (persons != null) {
                    for (person: Person in persons) {
                        Log.e("Person", person.name)
                    }
                }
            } else {
                Toast.makeText(mContext, ex.message, Toast.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>
<h1 id="_14">批量数据操作<a class="headerlink" href="#_14" title="Permanent link">&para;</a></h1>
<h2 id="_15">批量新增数据<a class="headerlink" href="#_15" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 批量新增数据
 */
private fun createBatch() {
    val gameScores = ArrayList&lt;BmobObject&gt;()
    for (i in 0..2) {
        val gameScore = GameScore()
        gameScore.playerName = "运动员$i"
        gameScores.add(gameScore)
    }

    /**
     * 3.5.0版本开始提供
     */
    BmobBatch().insertBatch(gameScores).doBatch(object : QueryListListener&lt;BatchResult&gt;() {
        override fun done(o: List&lt;BatchResult&gt;, e: BmobException?) {
            if (e == null) {
                for (i in o.indices) {
                    val result = o[i]
                    val ex = result.error
                    if (ex == null) {
                        Log.e("CREATE BATCH", "第" + i + "个数据批量添加成功：" + result.createdAt + "," + result.objectId + "," + result.updatedAt)
                    } else {
                        Log.e("CREATE BATCH", "第" + i + "个数据批量添加失败：" + ex.message + "," + ex.errorCode)
                    }
                }
            } else {
                Log.e("CREATE BATCH", "失败：" + e.message + "," + e.errorCode)
            }
        }
    })
}
</code></pre>
<h2 id="_16">批量更新数据<a class="headerlink" href="#_16" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 批量更新数据
 */
private fun updateBatch() {
    val gameScores = ArrayList&lt;BmobObject&gt;()
    val gameScore1 = GameScore()
    gameScore1.objectId = "此处填写已存在的objectId"
    val gameScore2 = GameScore()
    gameScore2.objectId = "此处填写已存在的objectId"
    gameScore2.playerName = "赵大"
    gameScore2.isPay = Boolean.FALSE
    val gameScore3 = GameScore()
    gameScore3.objectId = "此处填写已存在的objectId"
    gameScore3.playerName = "王二"

    gameScores.add(gameScore1)
    gameScores.add(gameScore2)
    gameScores.add(gameScore3)

    /**
     * 从3.5.0版本开始提供
     */
    BmobBatch().updateBatch(gameScores).doBatch(object : QueryListListener&lt;BatchResult&gt;() {

        override fun done(o: List&lt;BatchResult&gt;, ex: BmobException?) {
            if (ex == null) {
                for (i in o.indices) {
                    val result = o[i]
                    val ex = result.error
                    if (ex == null) {
                        Log.e("UPDATE", "第" + i + "个数据批量更新成功：" + result.updatedAt)
                    } else {
                        Log.e("UPDATE", "第" + i + "个数据批量更新失败：" + ex.message + "," + ex.errorCode)
                    }
                }
            } else {
                Log.e("UPDATE", "失败：" + ex.message + "," + ex.errorCode)
            }
        }
    })
}
</code></pre>
<h2 id="_17">批量删除操作<a class="headerlink" href="#_17" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 批量删除数据
 */
private fun deleteBatch() {
    val gameScores = ArrayList&lt;BmobObject&gt;()
    val gameScore1 = GameScore()
    gameScore1.objectId = "此处填写已存在的objectId"
    val gameScore2 = GameScore()
    gameScore2.objectId = "此处填写已存在的objectId"
    val gameScore3 = GameScore()
    gameScore3.objectId = "此处填写已存在的objectId"

    gameScores.add(gameScore1)
    gameScores.add(gameScore2)
    gameScores.add(gameScore3)


    /**
     * 3.5.0版本开始提供
     */
    BmobBatch().deleteBatch(gameScores).doBatch(object : QueryListListener&lt;BatchResult&gt;() {

        override fun done(o: List&lt;BatchResult&gt;, e: BmobException?) {
            if (e == null) {
                for (i in o.indices) {
                    val result = o[i]
                    val ex = result.error
                    if (ex == null) {
                        Log.e("DELETE BATCH", "第" + i + "个数据批量删除成功")
                    } else {
                        Log.e("DELETE BATCH", "第" + i + "个数据批量删除失败：" + ex.message + "," + ex.errorCode)
                    }
                }
            } else {
                Log.e("DELETE BATCH", "失败：" + e.message + "," + e.errorCode)
            }
        }
    })
}
</code></pre>
<h2 id="_18">批量新增、更新、删除同步操作<a class="headerlink" href="#_18" title="Permanent link">&para;</a></h2>
<p>/*<em>
     * 批量新增、更新、删除同步操作
     </em>/
    private fun doBatch() {</p>
<pre><code>    val batch = BmobBatch()


    //批量添加
    val gameScores = ArrayList&lt;BmobObject&gt;()
    val gameScore = GameScore()
    gameScore.playerName = "张三"
    gameScores.add(gameScore)
    batch.insertBatch(gameScores)

    //批量更新
    val gameScores1 = ArrayList&lt;BmobObject&gt;()
    val gameScore1 = GameScore()
    gameScore1.objectId = "此处填写已经存在的objectId"
    gameScore1.playerName = "李四"
    gameScores1.add(gameScore1)
    batch.updateBatch(gameScores1)

    //批量删除
    val gameScores2 = ArrayList&lt;BmobObject&gt;()
    val gameScore2 = GameScore()
    gameScore2.objectId = "此处填写已经存在的objectId"
    gameScores2.add(gameScore2)
    batch.deleteBatch(gameScores2)

    //从3.5.0版本开始提供
    batch.doBatch(object : QueryListListener&lt;BatchResult&gt;() {

        override fun done(results: List&lt;BatchResult&gt;, ex: BmobException?) {
            if (ex == null) {
                //返回结果的results和上面提交的顺序是一样的，请一一对应
                for (i in results.indices) {
                    val result = results[i]
                    if (result.isSuccess) {//只有批量添加才返回objectId
                        Log.e("BATCH", "第" + i + "个成功：" + result.objectId + "," + result.updatedAt)
                    } else {
                        val error = result.error
                        Log.e("BATCH", "第" + i + "个失败：" + error.errorCode + "," + error.message)
                    }
                }
            } else {
                Log.e("BATCH", "失败：" + ex.message + "," + ex.errorCode)
            }
        }
    })
}
</code></pre>
<h1 id="_19">注册登录<a class="headerlink" href="#_19" title="Permanent link">&para;</a></h1>
<h2 id="_20">用户名密码注册<a class="headerlink" href="#_20" title="Permanent link">&para;</a></h2>
<pre><code>    /**
     * bmob注册方法
     */
    var user = User()
    user.username = username
    user.setPassword(password)
    user.signUp(object : SaveListener&lt;User&gt;() {
        override fun done(currentUser: User?, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "注册成功", Toast.LENGTH_LONG).show()
                startActivity(Intent(mContext, MainActivity::class.java))
                finish()
            } else {
                Toast.makeText(mContext, ex.message, Toast.LENGTH_LONG).show()
            }
        }
    })
</code></pre>
<h2 id="_21">用户名密码登录<a class="headerlink" href="#_21" title="Permanent link">&para;</a></h2>
<pre><code>    /**
     * bmob登录方法
     */
    var user = User()
    user.username = username
    user.setPassword(password)
    user.login(object : SaveListener&lt;User&gt;() {
        override fun done(currentUser: User?, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "登录成功", Toast.LENGTH_LONG).show()
                startActivity(Intent(mContext,MainActivity::class.java))
                finish()
            } else {
                Toast.makeText(mContext, ex.message, Toast.LENGTH_LONG).show()
            }
        }
    })
</code></pre>
<h2 id="_22">修改密码<a class="headerlink" href="#_22" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 修改密码，必须先登录
 */
private fun resetPassword() {
    BmobUser.updateCurrentUserPassword(&quot;旧密码&quot;, &quot;新密码&quot;, object : UpdateListener() {
        override fun done(e: BmobException?) {
            if (e == null) {
                Snackbar.make(btn_reset, &quot;密码修改成功，可以用新密码进行登录啦&quot;, Snackbar.LENGTH_LONG).show()
            } else {
                Snackbar.make(btn_reset, &quot;密码修改失败：${e.message}&quot;, Snackbar.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>

<h1 id="_23">文件管理<a class="headerlink" href="#_23" title="Permanent link">&para;</a></h1>
<h2 id="_24">权限<a class="headerlink" href="#_24" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 适配android6.0 动态申请访问文件权限
 */
private fun requestPermission() {
    val checkSelfPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
    if (checkSelfPermission == PackageManager.PERMISSION_GRANTED) {
    } else {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_WRITE_CODE)
    }
}

/**
 * 权限申请回调结果
 */
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array&lt;out String&gt;, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == REQUEST_WRITE_CODE) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED &amp;&amp; permissions[0] == Manifest.permission.WRITE_EXTERNAL_STORAGE) {
            Toast.makeText(this, "permission granted", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this, "permission denied", Toast.LENGTH_SHORT).show()
        }
    }
}
</code></pre>
<h2 id="_25">上传单个文件<a class="headerlink" href="#_25" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 通过文件路径上传单个文件
 */
private fun uploadSingle(path: String?) {
    var file = File(path)
    var bmobFile = BmobFile(file)
    bmobFile.upload(object : UploadFileListener() {
        override fun done(ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "上传成功", Toast.LENGTH_SHORT).show()
                setFileToTable(bmobFile)
            } else {
                Toast.makeText(mContext, "上传失败："+ex.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
}
</code></pre>
<h2 id="_26">关联线上文件和表字段<a class="headerlink" href="#_26" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 将文件设置到表中
 */
private fun setFileToTable(bmobFile: BmobFile) {
    var person = Person()
    person.file = bmobFile
    person.save(object : SaveListener&lt;String&gt;() {
        override fun done(objectId: String?, ex: BmobException?) {
            Toast.makeText(mContext, "成功将文件设置到表中", Toast.LENGTH_LONG).show()
        }
    })
}
</code></pre>
<h2 id="_27">上传多个文件<a class="headerlink" href="#_27" title="Permanent link">&para;</a></h2>
<pre><code> /**
 * bmob  上传多个文件
 */
private fun uploadMultiFile() {
    /**
     * 此处修改为你手机的文件路径
     */
    var filePaths:Array&lt;String&gt; = arrayOf("/storage/emulated/0/1.png", "/storage/emulated/0/2.png", "/storage/emulated/0/3.png")
    BmobFile.uploadBatch(filePaths,object : UploadBatchListener {
        override fun onError(code: Int, error: String?) {
            Toast.makeText(mContext, "上传出错：$error",Toast.LENGTH_LONG).show()
        }

        override fun onProgress(curIndex: Int, curPercent: Int, total: Int, totalPercent: Int) {
            Toast.makeText(mContext, "上传进度：$curIndex",Toast.LENGTH_LONG).show()
        }

        override fun onSuccess(bmobFiles: MutableList&lt;BmobFile&gt;?, urls: MutableList&lt;String&gt;?) {
            if (urls != null) {
                if (urls.size==filePaths.size)
                    Toast.makeText(mContext, "全部上传成功",Toast.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>
<h2 id="_28">删除单个文件<a class="headerlink" href="#_28" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 删除单个文件
 */
private fun deleteSingleFile(bmobFile: BmobFile?) {
    bmobFile!!.delete(object :UpdateListener(){
        override fun done(ex: BmobException?) {
            if (ex==null){
                Toast.makeText(mContext, "删除成功", Toast.LENGTH_LONG).show()
            }else{
                Toast.makeText(mContext, ex.message, Toast.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>
<h2 id="_29">删除多个文件<a class="headerlink" href="#_29" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 删除多个文件
 */
private fun deleteMultiFiles(urls: Array&lt;String&gt;) {
    BmobFile.deleteBatch(urls,object :DeleteBatchListener(){
        override fun done(deleteUrls: Array&lt;out String&gt;?, ex: BmobException?) {
            if (ex==null){
                if (urls.size== deleteUrls!!.size){
                    Toast.makeText(mContext, "全部删除成功", Toast.LENGTH_LONG).show()
                }
            }else{
                Toast.makeText(mContext, ex.message, Toast.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>
<h1 id="_30">短信<a class="headerlink" href="#_30" title="Permanent link">&para;</a></h1>
<p>短信功能目前属于按需付费功能，请到应用设置--付费升级中购买短信量。</p>
<h2 id="_31">发送短信验证码<a class="headerlink" href="#_31" title="Permanent link">&para;</a></h2>
<pre><code>    /**
     * bmob发送验证码
     */
    BmobSMS.requestSMSCode(phone, "此处可填写控制台的短信模板名称，如果没有短信模板名称可填写空字符串使用默认模板", object : QueryListener&lt;Int&gt;() {
        override fun done(smsId: Int?, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "发送成功：$smsId", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mContext, "发送成失败：$ex.message", Toast.LENGTH_LONG).show()
            }
        }
    })
</code></pre>
<h2 id="_32">验证短信验证码<a class="headerlink" href="#_32" title="Permanent link">&para;</a></h2>
<pre><code>    /**
     * bmob验证验证码
     */
    BmobSMS.verifySmsCode(phone,code,object :UpdateListener(){
        override fun done(ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "验证成功", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mContext, "验证失败：$ex.message", Toast.LENGTH_LONG).show()
            }
        }
    })
</code></pre>
<h1 id="_33">邮箱<a class="headerlink" href="#_33" title="Permanent link">&para;</a></h1>
<p>邮箱功能目前属于按需付费功能，请到应用设置--付费升级中购买邮件量。</p>
<h2 id="_34">验证激活<a class="headerlink" href="#_34" title="Permanent link">&para;</a></h2>
<p>发送验证激活邮箱后，如果用户登录了邮箱并且点击了邮件中的激活链接，则可以使用邮箱+密码的方式进行登录。</p>
<pre><code>/**
 * 发送验证激活邮箱
 */
private fun sendEmailVerify() {
    val email = input_email.text.toString()
    if (TextUtils.isEmpty(email)){
        Toast.makeText(mContext,"请输入邮箱",Toast.LENGTH_LONG).show()
        return
    }
    BmobUser.requestEmailVerify(email, object : UpdateListener() {
        override fun done(e: BmobException?) {
            if (e == null) {
                Log.e("sendEmailVerify","请求验证邮件成功，请到" + email + "邮箱中进行激活。")
            } else {
                Log.e("sendEmailVerify","请求验证邮件失败:" + e.message)
            }
        }
    })
}
</code></pre>
<h2 id="_35">重置密码<a class="headerlink" href="#_35" title="Permanent link">&para;</a></h2>
<p>发送重置密码邮箱后，如果用户登录了邮箱并且点击邮件中的链接进行密码重置，则可以使用邮箱+新密码方式进行登录。</p>
<pre><code>/**
 * 发送重置密码邮箱
 */
private fun sendEmailReset() {
    val email = input_email.text.toString()
    if (TextUtils.isEmpty(email)){
        Toast.makeText(mContext,"请输入邮箱",Toast.LENGTH_LONG).show()
        return
    }
    BmobUser.resetPasswordByEmail(email, object : UpdateListener() {
        override fun done(e: BmobException?) {
            if (e == null) {
                Log.e("sendEmailReset","重置密码邮件成功，请到" + email + "邮箱中进行重置。")
            } else {
                Log.e("sendEmailReset","失败:" + e.message)
            }
        }
    })
}
</code></pre>
<h2 id="_36">邮箱+密码登录<a class="headerlink" href="#_36" title="Permanent link">&para;</a></h2>
<p>当邮箱通过验证激活后，即可使用邮箱+密码的方式进行登录。</p>
<pre><code>/**
 * 邮箱+密码登录
 */
private fun loginEmailPassword() {
    val email = input_email.text.toString()
    if (TextUtils.isEmpty(email)){
        Toast.makeText(mContext,"请输入邮箱",Toast.LENGTH_LONG).show()
        return
    }

    val password = input_password.text.toString()
    if (TextUtils.isEmpty(password)){
        Toast.makeText(mContext,"请输入邮箱",Toast.LENGTH_LONG).show()
        return
    }
    BmobUser.loginByAccount(email, password, object : LogInListener&lt;User&gt;() {
        override fun done(user: User?, ex: BmobException) {
            if (ex == null) {
                Log.e("loginByAccount","登录成功")
            } else {
                Log.e("loginByAccount","登录失败："+ex.message)
            }
        }
    })
}
</code></pre>
<h1 id="_37">第三方账号<a class="headerlink" href="#_37" title="Permanent link">&para;</a></h1>
<p>目前第三方账号功能只支持微博、QQ、微信三种社交账号。</p>
<h2 id="_38">注册登录<a class="headerlink" href="#_38" title="Permanent link">&para;</a></h2>
<p>在第三方账号授权成功之后调用。</p>
<pre><code>/**
 * 1、snsType:只能是三种取值中的一种：weibo、qq、weixin
 * 2、accessToken：接口调用凭证
 * 3、expiresIn：access_token的有效时间
 * 4、userId:用户身份的唯一标识，对应微博授权信息中的uid,对应qq和微信授权信息中的openid
 */
private fun thirdLoginSignup(snsType: String, accessToken: String, expiresIn: String, userId: String) {
    val authInfo = BmobUser.BmobThirdUserAuth(snsType, accessToken, expiresIn, userId)
    BmobUser.loginWithAuthData(authInfo, object : LogInListener&lt;JSONObject&gt;() {
        override fun done(data: JSONObject?, ex: BmobException?) {
            if (ex == null) {
                Log.e("loginWithAuthData", "登录注册成功")
            } else {
                Log.e("loginWithAuthData", "登录注册失败：" + ex.message)
            }
        }
    })
}
</code></pre>
<h2 id="_39">账号关联<a class="headerlink" href="#_39" title="Permanent link">&para;</a></h2>
<p>在第三方账号授权成功之后调用。</p>
<pre><code>/**
 * 关联第三方账号
 */
private fun associateThird(snsType: String, accessToken: String, expiresIn: String, userId: String) {
    val authInfo = BmobThirdUserAuth(snsType, accessToken, expiresIn, userId)
    BmobUser.associateWithAuthData(authInfo, object : UpdateListener() {

        override fun done(ex: BmobException?) {
            if (ex == null) {
                Log.e("associateWithAuthData", "关联成功")
            } else {
                Log.e("associateWithAuthData", "关联失败：" + ex.message)
            }
        }
    })
}
</code></pre>
<h2 id="_40">取消关联<a class="headerlink" href="#_40" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 取消关联
 */
private fun unAssociateThird(snsType: String) {
    var currentUser: User? = BmobUser.getCurrentUser(User::class.java)
    currentUser?.dissociateAuthData(snsType, object : UpdateListener() {

        override fun done(ex: BmobException?) {
            if (ex == null) {
                Log.e("dissociateAuthData", "取消关联成功")
            } else {
                Log.e("dissociateAuthData", "取消关联失败：" + ex.message)
            }
        }
    })
}
</code></pre>
<h1 id="_41">版本更新<a class="headerlink" href="#_41" title="Permanent link">&para;</a></h1>
<h2 id="_42">版本更新设置<a class="headerlink" href="#_42" title="Permanent link">&para;</a></h2>
<pre><code>    //TODO 初始化，当控制台表出现后，注释掉此句
    BmobUpdateAgent.initAppVersion();
    //TODO 设置仅WiFi环境更新
    BmobUpdateAgent.setUpdateOnlyWifi(false);
    //TODO 设置更新监听器
    BmobUpdateAgent.setUpdateListener(new BmobUpdateListener() {

        @Override
        public void onUpdateReturned(int updateStatus, UpdateResponse updateInfo) {
            BmobException e = updateInfo.getException();
            if (e == null) {
                updateResponse = updateInfo;
                Toast.makeText(MainActivity.this, "检测更新返回：" + updateInfo.version + "-" + updateInfo.path, Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(MainActivity.this, "检测更新返回：" + e.getMessage() + "(" + e.getErrorCode() + ")", Toast.LENGTH_SHORT).show();
            }
        }
    });
    //TODO 设置对话框监听器
    BmobUpdateAgent.setDialogListener(new BmobDialogButtonListener() {

        @Override
        public void onClick(int status) {
            switch (status) {
                case UpdateStatus.Update:
                    Toast.makeText(MainActivity.this, "点击了立即更新按钮", Toast.LENGTH_SHORT).show();
                    break;
                case UpdateStatus.NotNow:
                    Toast.makeText(MainActivity.this, "点击了以后再说按钮", Toast.LENGTH_SHORT).show();
                    break;
                case UpdateStatus.Close:
                    Toast.makeText(MainActivity.this, "点击了对话框关闭按钮", Toast.LENGTH_SHORT).show();
                    break;

                default:
                    break;
            }
        }
    });
</code></pre>
<h2 id="_43">动态访问权限<a class="headerlink" href="#_43" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 检查权限
 *
 * @param requestCode
 */
public void checkStoragePermissions(int requestCode) {
    List&lt;String&gt; permissions = new ArrayList&lt;&gt;();
    int permissionCheckWrite = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    if (permissionCheckWrite != PackageManager.PERMISSION_GRANTED) {
        permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }
    int permissionCheckRead = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
    if (permissionCheckRead != PackageManager.PERMISSION_GRANTED) {
        permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
    }
    if (permissions.size() &gt; 0) {
        String[] missions = new String[]{};
        ActivityCompat.requestPermissions(this, permissions.toArray(missions), requestCode);
    } else {
        switch (requestCode) {
            case REQUEST_AUTO:
                BmobUpdateAgent.update(this);
                break;
            case REQUEST_CHECK:
                BmobUpdateAgent.forceUpdate(this);
                break;
            case REQUEST_SILENT:
                BmobUpdateAgent.silentUpdate(this);
                break;
            case REQUEST_DELETE:
                BmobUpdateAgent.deleteResponse(updateResponse);
                break;
            default:
                break;
        }
    }
}


/**
 * 检查授权结果
 *
 * @param grantResults
 * @return
 */
public boolean checkResults(int[] grantResults) {
    if (grantResults == null || grantResults.length &lt; 1) {
        return false;
    }
    for (int result : grantResults) {
        if (result == PackageManager.PERMISSION_DENIED) {
            return false;
        }
    }
    return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case REQUEST_AUTO:
            if (checkResults(grantResults)) {
                BmobUpdateAgent.update(this);
            }
            break;
        case REQUEST_CHECK:
            if (checkResults(grantResults)) {
                BmobUpdateAgent.forceUpdate(this);
            }
            break;
        case REQUEST_SILENT:
            if (checkResults(grantResults)) {
                BmobUpdateAgent.silentUpdate(this);
            }
            break;
        case REQUEST_DELETE:
            if (checkResults(grantResults)) {
                BmobUpdateAgent.deleteResponse(updateResponse);
            }
            break;
        default:
            break;
    }
}
</code></pre>
<h2 id="_44">清单文件设置<a class="headerlink" href="#_44" title="Permanent link">&para;</a></h2>
<pre><code>    &lt;!--数据共享--&gt;
    &lt;provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="cn.bmob.kotlin.data"
        android:exported="false"
        android:grantUriPermissions="true"&gt;
        &lt;meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/&gt;
    &lt;/provider&gt;

    &lt;activity
        android:name="cn.bmob.v3.update.UpdateDialogActivity"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"&gt;
    &lt;/activity&gt;
</code></pre>
<h1 id="_45">数据监听<a class="headerlink" href="#_45" title="Permanent link">&para;</a></h1>
<p>1、start方法开始连接；</p>
<p>2、onConnectCompleted回调方法后判断是否连接成功，若成功则设置监听内容；</p>
<p>3、onDataChange回调方法返回监听到的更新内容。</p>
<p>4、数据监听目前属于按需付费，请到应用设置--付费升级中购买。</p>
<pre><code>private fun startListen() {
    val rtd = BmobRealTimeData()
    rtd.start(object : ValueEventListener {
        override fun onDataChange(data: JSONObject) {
            Log.d("onDataChange", "(" + data.optString("action") + ")" + "数据：" + data)
            val action = data.optString("action")
            if (action == BmobRealTimeData.ACTION_UPDATETABLE) {
                //TODO 如果监听表更新
                val data = data.optJSONObject("data")
                Toast.makeText(mContext, "监听到更新：" + data.optString("name") + "-" + data.optString("content"), Toast.LENGTH_SHORT).show()
            }
        }

        override fun onConnectCompleted(ex: Exception) {
            if (ex == null) {
                Log.i("onConnectCompleted", "连接情况：" + if (rtd.isConnected) "已连接" else "未连接")
                if (rtd.isConnected) {
                    //TODO 如果已连接，设置监听动作为：监听Chat表的更新
                    rtd.subTableUpdate("Chat")
                }
            } else {
                Log.e("onConnectCompleted", "连接出错：" + ex.message)
            }
        }
    })
}
</code></pre>
<h1 id="acl">ACL<a class="headerlink" href="#acl" title="Permanent link">&para;</a></h1>
<p>新增一条帖子数据，并且置当前用户可写，设置所有人可读。</p>
<pre><code>/**
 * ACL控制一条数据的访问权限
 */
private fun aclAccess() {
    val user = BmobUser.getCurrentUser(User::class.java)

    val acl = BmobACL()    //创建一个ACL对象
    acl.setPublicReadAccess(true)  // 设置所有人可读的权限
    acl.setWriteAccess(user, true)   // 设置当前用户可写的权限

    val post = Post()
    post.author = user
    post.title="ACL"
    post.content="ACL控制访问权限"
    post.save(object : SaveListener&lt;String&gt;(){
        override fun done(objectId: String?, ex: BmobException?) {
            if (ex == null) {
                Log.e("ACL", "保存成功")
            } else {
                Log.e("ACL", "保存失败：" + ex.message)
            }
        }
    })
}
</code></pre>
<h1 id="_46">角色<a class="headerlink" href="#_46" title="Permanent link">&para;</a></h1>
<pre><code>/**
 * BmobRole：角色访问管理权限
 */
private fun roleAccess() {
    //创建公司某用户的工资对象
    val wage = Wage()
    wage.wage= 10000.0

    //这里创建四个用户对象，分别为老板、人事小张、出纳小谢和自己
    val boss: BmobUser? =null
    val hr_zhang: BmobUser? =null
    val hr_luo: BmobUser? =null
    val cashier_xie: BmobUser? =null
    val me: BmobUser? =null

    //创建HR和Cashier两个用户角色（这里为了举例BmobRole的使用，将这段代码写在这里，正常情况下放在员工管理界面会更合适）
    val hr = BmobRole("HR")
    val cashier = BmobRole("Cashier")

    //将hr_zhang和hr_luo归属到hr角色中
    hr.users.add(hr_zhang)
    hr.users.add(hr_luo)
    //保存到云端角色表中（web端可以查看Role表）
    hr.save(object :SaveListener&lt;String&gt; (){
        override fun done(objectId: String?, ex: BmobException?) {
            if (ex == null) {
                Log.e("ROLE", "保存成功")
            } else {
                Log.e("ROLE", "保存失败：" + ex.message)
            }
        }
    })

    //将cashier_xie归属到cashier角色中
    cashier.users.add(cashier_xie)
    //保存到云端角色表中（web端可以查看Role表）
    cashier.save(object :SaveListener&lt;String&gt; (){
        override fun done(objectId: String?, ex: BmobException?) {
            if (ex == null) {
                Log.e("ROLE", "保存成功")
            } else {
                Log.e("ROLE", "保存失败：" + ex.message)
            }
        }
    })

    //创建ACL对象
    val acl = BmobACL()
    acl.setReadAccess(boss, true) // 假设老板只有一个, 设置读权限
    acl.setReadAccess(me, true) // 给自己设置读权限
    acl.setRoleReadAccess(hr, true) // 给hr角色设置读权限
    acl.setRoleReadAccess(cashier, true) // 给cashier角色设置读权限

    acl.setWriteAccess(boss, true) // 设置老板拥有写权限
    acl.setRoleWriteAccess(hr, true) // 设置hr角色拥有写权限

    //设置工资对象的ACL
    wage.acl = acl
    wage.save(object :SaveListener&lt;String&gt;(){
        override fun done(objectId: String?, ex: BmobException?) {
            if (ex == null) {
                Log.e("ROLE", "保存成功")
            } else {
                Log.e("ROLE", "保存失败：" + ex.message)
            }
        }
    })
}
</code></pre>
<h1 id="_47">数组<a class="headerlink" href="#_47" title="Permanent link">&para;</a></h1>
<h3 id="_48">添加数组<a class="headerlink" href="#_48" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 添加数组
 */
private fun addArray() {
    val user = BmobUser.getCurrentUser(User::class.java)
    if (user==null){
        Snackbar.make(btn_array_add,&quot;请先登录&quot;,Snackbar.LENGTH_LONG).show()
        return
    }
    user.add(&quot;hobbies&quot;, &quot;唱歌&quot;)
    user.update(object :UpdateListener(){
        override fun done(e: BmobException?) {
            if(e==null){
                Log.i(&quot;bmob&quot;,&quot;更新成功&quot;)
            }else{
                Log.i(&quot;bmob&quot;,&quot;更新失败：&quot;+e.message)
            }  
        }
    })
}
</code></pre>

<h3 id="_49">更新数组<a class="headerlink" href="#_49" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 更新数组
 */
private fun updateArray() {
    val user = BmobUser.getCurrentUser(User::class.java)
    if (user == null) {
        Snackbar.make(btn_array_add, &quot;请先登录&quot;, Snackbar.LENGTH_LONG).show()
        return
    }
    user.setValue(&quot;hobbies.0&quot;, &quot;爬山&quot;)
    user.update(object : UpdateListener() {
        override fun done(e: BmobException?) {
            if (e == null) {
                Snackbar.make(btn_array_add, &quot;更新成功&quot;, Snackbar.LENGTH_LONG).show()
            } else {
                Snackbar.make(btn_array_add, &quot;更新失败：&quot; + e.message, Snackbar.LENGTH_LONG).show()
            }
        }
    })
}

</code></pre>

<h3 id="_50">删除数组<a class="headerlink" href="#_50" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 删除数组
 */
private fun deleteArray() {
    val user = BmobUser.getCurrentUser(User::class.java)
    if (user == null) {
        Snackbar.make(btn_array_add, &quot;请先登录&quot;, Snackbar.LENGTH_LONG).show()
        return
    }
    user.removeAll(&quot;hobbies&quot;, Arrays.asList(&quot;阅读&quot;, &quot;唱歌&quot;, &quot;游泳&quot;))
    user.update(object : UpdateListener() {

        override fun done(e: BmobException?) {
            if (e == null) {
                Log.i(&quot;bmob&quot;, &quot;成功&quot;)
            } else {
                Log.i(&quot;bmob&quot;, &quot;失败：&quot; + e.message)
            }
        }
    })
}

</code></pre>

<h1 id="_51">位置<a class="headerlink" href="#_51" title="Permanent link">&para;</a></h1>
<pre><code>/**
 * 查询矩形范围内的用户
 */
private fun queryRectangle() {
    val query = BmobQuery&lt;User&gt;()
    val southwestOfSF = BmobGeoPoint(112.934755, 24.52065)
    val northeastOfSF = BmobGeoPoint(116.627623, 40.143687)
    query.addWhereWithinGeoBox("location", southwestOfSF, northeastOfSF)
    query.findObjects(object : FindListener&lt;User&gt;() {
        override fun done(persons: List&lt;User&gt;, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "查询成功", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mContext, "查询失败：${ex.message}", Toast.LENGTH_LONG).show()
            }
        }
    })
}


/**
 * 查询指定距离范围内的用户
 */
private fun queryDistance() {
    val query = BmobQuery&lt;User&gt;()
    val southwestOfSF = BmobGeoPoint(112.934755, 24.52065)
    //查询指定坐标指定半径内的用户
    query.addWhereWithinRadians("location", southwestOfSF, 10.0)
    query.findObjects(object : FindListener&lt;User&gt;() {
        override fun done(persons: List&lt;User&gt;, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "查询成功", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mContext, "查询失败：${ex.message}", Toast.LENGTH_LONG).show()
            }
        }
    })
}


/**
 * 查询最接近某个坐标的用户
 */
private fun queryShortest() {
    val query = BmobQuery&lt;User&gt;()
    val location = BmobGeoPoint(112.934755, 24.52065)
    query.addWhereNear("location", location)
    query.setLimit(10)
    query.findObjects(object : FindListener&lt;User&gt;() {
        override fun done(persons: List&lt;User&gt;, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, "查询成功", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mContext, "查询失败：${ex.message}", Toast.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>
<h1 id="_52">关联关系<a class="headerlink" href="#_52" title="Permanent link">&para;</a></h1>
<h2 id="_53">一对一关联<a class="headerlink" href="#_53" title="Permanent link">&para;</a></h2>
<h3 id="_54">添加一对一关系<a class="headerlink" href="#_54" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 发布帖子
 */
private fun publishPost() {
    val content = input_post.text.toString()
    if (TextUtils.isEmpty(content)) {
        Toast.makeText(mContext, &quot;请输入内容&quot;, Toast.LENGTH_LONG).show()
        return
    }

    val user = BmobUser.getCurrentUser(User::class.java)
    if(user==null) {
        Toast.makeText(mContext, &quot;请先登录&quot;, Toast.LENGTH_LONG).show()
        return
    }
    val post = Post()
    post.content = content
    post.author = user
    post.save(object : SaveListener&lt;String&gt;() {
        override fun done(objectId: String?, ex: BmobException?) {
            if (ex == null) {
                Toast.makeText(mContext, &quot;发布成功&quot;, Toast.LENGTH_LONG).show()
                finish()
            } else {
                Toast.makeText(mContext, &quot;发布失败：${ex.message}&quot;, Toast.LENGTH_LONG).show()
            }
        }
    })
}

</code></pre>

<h3 id="_55">查询一对一关系<a class="headerlink" href="#_55" title="Permanent link">&para;</a></h3>
<pre><code>    val user = BmobUser.getCurrentUser&lt;User&gt;(User::class.java)
    val query = BmobQuery&lt;Post&gt;()
    query.addWhereEqualTo("author", user)  // 查询当前用户的所有帖子
    query.order("-updatedAt")
    query.include("author")// 希望在查询帖子信息的同时也把发布人的信息查询出来
    query.findObjects(object : FindListener&lt;Post&gt;() {

        override fun done(posts: List&lt;Post&gt;, e: BmobException?) {
            if (e == null) {
                Log.i("bmob", "成功")
            } else {
                Log.i("bmob", "失败：" + e.message)
            }
        }
    })
</code></pre>
<h2 id="_56">一对多关联<a class="headerlink" href="#_56" title="Permanent link">&para;</a></h2>
<h3 id="_57">添加一对多关系<a class="headerlink" href="#_57" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 
 */
private fun addComment(objectId: String?) {
    val user = BmobUser.getCurrentUser&lt;User&gt;(User::class.java)
    val content = input_comment_content.text.toString()
    val post = Post()
    post.objectId = objectId
    val comment = Comment()
    comment.content = content
    comment.user = user
    comment.post = post
    comment.save(object : SaveListener&lt;String&gt;() {

        override fun done(objectId: String, e: BmobException?) {
            if (e == null) {
                Snackbar.make(btn_add_comment, &quot;评论发表成功&quot;, Snackbar.LENGTH_LONG).show()
            } else {
                Snackbar.make(btn_add_comment, &quot;评论发表失败：&quot; + e.message, Snackbar.LENGTH_LONG).show()
            }
        }

    })
}

</code></pre>

<h3 id="_58">查询一对多关系<a class="headerlink" href="#_58" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 查询帖子的所有评论
 */
private fun queryComment(objectId: String?) {
    val query = BmobQuery&lt;Comment&gt;()
    val post = Post()
    //用此方式可以构造一个BmobPointer对象。只需要设置objectId就行
    post.objectId = objectId
    query.addWhereEqualTo(&quot;post&quot;, BmobPointer(post))
    //希望同时查询该评论的发布者的信息，以及该帖子的作者的信息，这里用到上面`include`的并列对象查询和内嵌对象的查询
    query.include(&quot;user,post.author&quot;)
    query.findObjects(object :FindListener&lt;Comment&gt;(){
        override fun done(comments: MutableList&lt;Comment&gt;?, ex: BmobException?) {

            if (ex == null) {
                Snackbar.make(btn_add_comment, &quot;评论发表成功&quot;, Snackbar.LENGTH_LONG).show()
            } else {
                Snackbar.make(btn_add_comment, &quot;评论发表失败：&quot; + ex.message, Snackbar.LENGTH_LONG).show()
            }
        }

    })
}
</code></pre>

<h2 id="_59">多对多关联<a class="headerlink" href="#_59" title="Permanent link">&para;</a></h2>
<h3 id="_60">添加多对多关系<a class="headerlink" href="#_60" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 喜欢该帖子
 */
private fun like(objectId: String?) {
    val user = BmobUser.getCurrentUser&lt;User&gt;(User::class.java)
    if (user != null) {
        Snackbar.make(btn_like, &quot;请先登录&quot;, Snackbar.LENGTH_LONG).show()
        return
    }
    val post = Post()
    post.objectId = objectId
    //将当前用户添加到Post表中的likes字段值中，表明当前用户喜欢该帖子
    val relation = BmobRelation()
    //将当前用户添加到多对多关联中
    relation.add(user)
    //多对多关联指向`post`的`likes`字段
    post.likes = relation
    post.update(object : UpdateListener() {
        override fun done(e: BmobException?) {
            if (e == null) {
                Snackbar.make(btn_like, &quot;多对多关联添加成功&quot;, Snackbar.LENGTH_LONG).show()
            } else {
                Snackbar.make(btn_like, &quot;多对多关联添加失败：&quot; + e.message, Snackbar.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>

<h3 id="_61">查询多对多关系<a class="headerlink" href="#_61" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 查询喜欢该帖子的所有用户
 */
private fun likes(objectId: String?) {
    // 查询喜欢这个帖子的所有用户，因此查询的是用户表
    val query = BmobQuery&lt;User&gt;()
    val post = Post()
    post.objectId = objectId
    //likes是Post表中的字段，用来存储所有喜欢该帖子的用户
    query.addWhereRelatedTo(&quot;likes&quot;, BmobPointer(post))
    query.findObjects(object : FindListener&lt;User&gt;() {
        override fun done(users: List&lt;User&gt;, e: BmobException?) {
            if (e == null) {
                Snackbar.make(btn_likes, &quot;查询成功：&quot; + users.size, Snackbar.LENGTH_LONG).show()
            } else {
                Snackbar.make(btn_likes, &quot;查询失败：&quot; + e.message, Snackbar.LENGTH_LONG).show()
            }
        }
    })
}

</code></pre>

<h3 id="_62">删除多对多关系<a class="headerlink" href="#_62" title="Permanent link">&para;</a></h3>
<pre><code>/**
 * 取消喜欢该帖子
 */
private fun unlike(objectId: String?) {
    val post = Post()
    post.objectId = objectId
    val user = BmobUser.getCurrentUser&lt;User&gt;(User::class.java!!)
    val relation = BmobRelation()
    relation.remove(user)
    post.likes = relation
    post.update(object : UpdateListener() {

        override fun done(e: BmobException?) {
            if (e == null) {
                Snackbar.make(btn_unlike, &quot;关联关系删除成功&quot;, Snackbar.LENGTH_LONG).show()
            } else {
                Snackbar.make(btn_likes, &quot;关联关系删除失败：&quot; + e.message, Snackbar.LENGTH_LONG).show()
            }
        }

    })
}

</code></pre>

<h1 id="_63">服务器时间<a class="headerlink" href="#_63" title="Permanent link">&para;</a></h1>
<p>考虑到安全问题，要求客户端的时间必须是正常时间，否则会返回"sdk time error"错误，如果出现此问题，可以先获取服务器时间，再设置好客户端时间后重新请求。</p>
<pre><code>/**
 * 获取服务器时间
 */
private fun getBmobServerTime() {
    Bmob.getServerTime(object : QueryListener&lt;Long&gt;() {
        override fun done(time: Long, e: BmobException?) {
            if (e == null) {
                val formatter = SimpleDateFormat(&quot;yyyy-MM-dd HH:mm&quot;)
                val times = formatter.format(Date(time * 1000L))
                Snackbar.make(btn_get_server_time,&quot;当前服务器时间为:$times&quot;,Snackbar.LENGTH_LONG).show()
            } else {
                Snackbar.make(btn_get_server_time,&quot;获取服务器时间失败:&quot; + e.message,Snackbar.LENGTH_LONG).show()
            }
        }
    })
}
</code></pre>

<h1 id="_64">表结构<a class="headerlink" href="#_64" title="Permanent link">&para;</a></h1>
<h2 id="_65">获取单表结构<a class="headerlink" href="#_65" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 获取某张表的表结构
 */
private fun getTable(table: String?) {
    Bmob.getTableSchema(table, object : QueryListener&lt;BmobTableSchema&gt;() {

        override fun done(schema: BmobTableSchema, ex: BmobException?) {
            if (ex == null) {
                Log.i(&quot;bmob&quot;, &quot;获取指定表的表结构信息成功：&quot; + schema.className + &quot;-&quot; + schema.fields.toString())
            } else {
                Log.i(&quot;bmob&quot;, &quot;获取指定表的表结构信息失败:&quot; + ex.localizedMessage + &quot;(&quot; + ex.errorCode + &quot;)&quot;)
            }
        }
    })
}

</code></pre>

<h2 id="_66">获取所有表结构<a class="headerlink" href="#_66" title="Permanent link">&para;</a></h2>
<pre><code>/**
 * 获取所有表结构
 */
private fun getAllTable() {

    Bmob.getAllTableSchema(object : QueryListListener&lt;BmobTableSchema&gt;() {

        override fun done(schemas: List&lt;BmobTableSchema&gt;?, ex: BmobException?) {
            if (ex == null &amp;&amp; schemas != null &amp;&amp; schemas.isNotEmpty()) {
                Log.i(&quot;bmob&quot;, &quot;获取所有表结构信息成功&quot;)
            } else {
                Log.i(&quot;bmob&quot;, &quot;获取所有表结构信息失败：&quot; + ex!!.localizedMessage + &quot;(&quot; + ex.errorCode + &quot;)&quot;)
            }
        }
    })
}
</code></pre>
                </div>
            </div>
        </div>

        
            <script>var base_url = '../..';</script>
            <script src="../../js/jquery-1.10.2.min.js"></script>
            <script src="../../js/bootstrap-3.0.3.min.js"></script>
            <script src="../../js/highlight.pack.js"></script>
            <script src="../../js/main.js"></script>
            <script src="../../js/base.js"></script>

        <div id="go-top"><i class="fa fa-chevron-up"></i></div>
        <a href="https://docs.bmob.cn/data/Android/a_faststart/doc/index.html" id="back" target="_blank">返回 <br> 旧版</a>
    </body>

</html>